Перейти к основному содержимому

5.03. Справочник по Java

Разработчику Архитектору

Справочник по Java

1. Основные понятия и структура программы

1.1. Класс

Каждая программа на Java начинается с определения класса. Класс — это шаблон для создания объектов, содержащий поля (переменные) и методы (функции).

public class MyClass {
// тело класса
}

1.2. Метод main

Точка входа в программу — метод main. Он должен быть статическим, иметь модификатор public, возвращать void и принимать массив строк в качестве аргумента.

public static void main(String[] args) {
// точка входа
}

1.3. Пакеты

Пакеты группируют связанные классы и интерфейсы. Объявление пакета — первая исполняемая строка в файле (кроме комментариев).

package com.example.myapp;

1.4. Импорты

Инструкции import подключают классы из других пакетов. Можно импортировать отдельные классы или все классы пакета с помощью звёздочки.

import java.util.List;
import java.util.*;

2. Типы данных

2.1. Примитивные типы

ТипРазмер (бит)Диапазон значенийЗначение по умолчанию
byte8от -128 до 1270
short16от -32 768 до 32 7670
int32от -2³¹ до 2³¹ - 10
long64от -2⁶³ до 2⁶³ - 10L
float32приблизительно ±3.40282347E+38F0.0f
double64приблизительно ±1.79769313486231570E+3080.0d
char16от \u0000 (0) до \uffff (65 535)'\u0000'
booleantrue или falsefalse

2.2. Обёрточные классы (Wrapper Classes)

Каждому примитивному типу соответствует класс-обёртка:

  • Byte
  • Short
  • Integer
  • Long
  • Float
  • Double
  • Character
  • Boolean

Эти классы позволяют использовать примитивы как объекты, поддерживают методы преобразования, сравнения и парсинга.

Пример:

Integer num = Integer.valueOf(42);
int primitive = num.intValue();

2.3. Ссылочные типы

Ссылочные типы включают:

  • Классы (String, пользовательские классы)
  • Интерфейсы
  • Массивы
  • Перечисления (enum)
  • Аннотации

Значение ссылочного типа — это адрес объекта в куче. Значение по умолчанию — null.


3. Переменные

3.1. Объявление и инициализация

int age = 25;
String name = "Alice";
boolean isActive = true;

3.2. Область видимости

  • Локальные переменные: объявлены внутри метода или блока. Должны быть инициализированы перед использованием.
  • Поля класса (instance variables): принадлежат объекту. Инициализируются значениями по умолчанию.
  • Статические поля (class variables): принадлежат классу. Объявляются с ключевым словом static.

3.3. Модификаторы доступа для полей

  • public — доступ из любого места
  • protected — доступ из того же пакета и подклассов
  • default (без модификатора) — доступ только в пределах пакета
  • private — доступ только внутри класса

4. Операторы

4.1. Арифметические

  • + — сложение
  • - — вычитание
  • * — умножение
  • / — деление
  • % — остаток от деления

4.2. Унарные

  • + — унарный плюс
  • - — унарный минус
  • ++ — инкремент
  • -- — декремент
  • ! — логическое НЕ (для boolean)

4.3. Операторы присваивания

  • =
  • +=, -=, *=, /=, %=

4.4. Операторы сравнения

  • == — равенство (для примитивов — значение, для ссылок — адрес)
  • != — неравенство
  • <, <=, >, >=

4.5. Логические операторы

  • && — логическое И (с коротким замыканием)
  • || — логическое ИЛИ (с коротким замыканием)
  • & — побитовое И / логическое И без короткого замыкания
  • | — побитовое ИЛИ / логическое ИЛИ без короткого замыкания
  • ^ — исключающее ИЛИ (XOR)

4.6. Побитовые операторы

  • ~ — побитовое НЕ
  • << — сдвиг влево
  • >> — арифметический сдвиг вправо
  • >>> — логический сдвиг вправо

4.7. Тернарный оператор

int max = (a > b) ? a : b;

4.8. Оператор instanceof

Проверяет, является ли объект экземпляром указанного класса или интерфейса.

if (obj instanceof String) { ... }

5. Управляющие конструкции

5.1. Условные операторы

if-else

if (condition) {
// код
} else if (anotherCondition) {
// код
} else {
// код
}

switch (до Java 13 и после)

Поддерживает byte, short, char, int, String, enum, и начиная с Java 17 — sealed-классы.

Java 14+ поддерживает выражения switch:

int dayValue = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};

5.2. Циклы

for

for (int i = 0; i < 10; i++) { ... }

for-each (enhanced for)

for (String item : list) { ... }

while

while (condition) { ... }

do-while

do {
// код
} while (condition);

5.3. Операторы управления потоком

  • break — выход из цикла или switch
  • continue — переход к следующей итерации цикла
  • return — выход из метода с возвратом значения (если метод не void)

Можно использовать метки для выхода из вложенных циклов:

outer: for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (someCondition) break outer;
}
}

6. Методы

6.1. Сигнатура метода

[модификаторы] тип_возврата имя([параметры]) [throws исключения]

Пример:

public static int add(int a, int b) {
return a + b;
}

6.2. Перегрузка методов

Методы с одинаковым именем, но разными параметрами (тип, количество, порядок).

6.3. Вариадические методы

Принимают переменное число аргументов одного типа:

public void printAll(String... messages) {
for (String msg : messages) System.out.println(msg);
}

Вызов:

printAll("A", "B", "C");

6.4. Рекурсия

Метод вызывает сам себя. Должно быть условие завершения.

public int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}

7. Классы и объекты

7.1. Конструкторы

  • Имя совпадает с именем класса
  • Не имеют возвращаемого типа
  • Вызываются при создании объекта через new
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
}

7.2. Ключевое слово this

Ссылается на текущий экземпляр объекта. Используется для:

  • Разрешения конфликта имён (параметр vs поле)
  • Вызова другого конструктора (this(...))
  • Возврата текущего объекта

7.3. Статические члены

Объявляются с static. Принадлежат классу, а не экземпляру.

public static final double PI = 3.14159;

7.4. Блоки инициализации

  • Статический блок: выполняется один раз при загрузке класса
  • Блок инициализации экземпляра: выполняется перед каждым конструктором
static {
// инициализация статических полей
}

{
// инициализация полей экземпляра
}

8. Наследование и полиморфизм

8.1. Ключевое слово extends

Класс наследует поля и методы другого класса.

class Animal { ... }
class Dog extends Animal { ... }

8.2. Ключевое слово super

  • Вызов конструктора родителя: super(...)
  • Доступ к полям и методам родителя: super.method()

8.3. Переопределение методов (Override)

Метод в подклассе заменяет метод родительского класса. Должен иметь:

  • То же имя
  • Те же параметры
  • Совместимый тип возврата
  • Уровень доступа не уже, чем у родителя

Аннотация @Override обязательна для явного указания намерения.

8.4. Запрет наследования

Класс, помеченный final, не может быть унаследован.

public final class MathUtils { ... }

9. Интерфейсы и абстрактные классы

9.1. Интерфейс (interface)

Интерфейс — это контракт, определяющий набор методов, которые должны быть реализованы классом. Начиная с Java 8, интерфейсы могут содержать:

  • Абстрактные методы (без тела)
  • Методы по умолчанию (default) — с реализацией
  • Статические методы
  • Частные методы (private) — начиная с Java 9
public interface Drawable {
void draw(); // абстрактный метод

default void resize() {
System.out.println("Resizing...");
}

static boolean isSupported() {
return true;
}
}

Класс реализует интерфейс с помощью ключевого слова implements.

public class Circle implements Drawable {
public void draw() {
System.out.println("Drawing a circle");
}
}

Один класс может реализовывать несколько интерфейсов.

9.2. Абстрактный класс (abstract class)

Абстрактный класс — это класс, который не может быть инстанцирован напрямую и может содержать как абстрактные, так и конкретные методы.

public abstract class Shape {
protected String color;

public abstract double area();

public void setColor(String color) {
this.color = color;
}
}

Подкласс обязан реализовать все абстрактные методы, если сам не является абстрактным.

9.3. Отличия

  • Интерфейс поддерживает множественное наследование поведения.
  • Абстрактный класс позволяет наследовать состояние (поля) и частичную реализацию.
  • Интерфейсы не имеют конструкторов; абстрактные классы — имеют.

10. Исключения (Exceptions)

10.1. Иерархия исключений

  • Throwable — корень иерархии
    • Error — фатальные ошибки (например, OutOfMemoryError)
    • Exception
      • Проверяемые (checked) — компилятор требует обработки (IOException, SQLException)
      • Непроверяемые (unchecked) — наследники RuntimeException (NullPointerException, IllegalArgumentException)

10.2. Обработка исключений

try {
// код, который может выбросить исключение
} catch (IOException e) {
// обработка
} finally {
// всегда выполняется
}

10.3. Множественные catch

catch (IOException | SQLException e) {
// обработка нескольких типов
}

10.4. Try-with-resources (Java 7+)

Автоматическое закрытие ресурсов, реализующих AutoCloseable.

try (FileInputStream fis = new FileInputStream("file.txt")) {
// работа с файлом
} // fis.close() вызывается автоматически

10.5. Создание собственных исключений

public class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message);
}
}

11. Дженерики (Generics)

11.1. Основы

Дженерики обеспечивают типобезопасность при компиляции.

List<String> names = new ArrayList<>();
names.add("Alice");
// names.add(123); // ошибка компиляции

11.2. Параметры типа

  • T — Type
  • E — Element
  • K — Key
  • V — Value
  • N — Number

11.3. Ограничения

  • ? — wildcard (неизвестный тип)
  • ? extends T — верхняя граница (любой подтип T)
  • ? super T — нижняя граница (любой надтип T)

Пример:

public void copy(List<? extends Number> src, List<? super Number> dest) { ... }

11.4. Стирание типов (Type Erasure)

Во время выполнения информация о дженериках недоступна. Это ограничивает рефлексию и запрещает создание массивов параметризованных типов.


12. Коллекции (Collections Framework)

12.1. Иерархия основных интерфейсов

  • Collection
    • List — упорядоченная коллекция с дубликатами (ArrayList, LinkedList)
    • Set — без дубликатов (HashSet, LinkedHashSet, TreeSet)
    • Queue — очередь (LinkedList, PriorityQueue, ArrayDeque)
  • Map — ассоциативный массив (HashMap, LinkedHashMap, TreeMap, Hashtable)

12.2. Основные реализации

ТипОсобенности
ArrayListБыстрый доступ по индексу, медленные вставки/удаления в середине
LinkedListБыстрые вставки/удаления, медленный доступ по индексу
HashSetНа основе хеш-таблицы, неупорядоченный
TreeSetСортированный, основан на красно-черном дереве
HashMapКлюч-значение, неупорядоченный, допускает null
TreeMapСортированный по ключу

12.3. Утилиты

  • Collections — статические методы для работы с коллекциями (sort, reverse, synchronizedList)
  • Arrays — методы для массивов (asList, sort, binarySearch)

12.4. Stream API (Java 8+)

Позволяет функционально обрабатывать коллекции.

List<String> result = names.stream()
.filter(n -> n.startsWith("A"))
.map(String::toUpperCase)
.collect(Collectors.toList());

13. Многопоточность

13.1. Создание потоков

  • Через наследование Thread
  • Через реализацию Runnable
  • Через ExecutorService
Thread t = new Thread(() -> {
System.out.println("Running in thread");
});
t.start();

13.2. Пул потоков

ExecutorService executor = Executors.newFixedThreadPool(4);
executor.submit(() -> { /* задача */ });
executor.shutdown();

13.3. Синхронизация

  • synchronized — блок или метод
  • volatile — гарантирует видимость изменений между потоками
  • Lock — гибкая альтернатива (ReentrantLock)
  • AtomicInteger, AtomicReference — атомарные операции без блокировок

13.4. CompletableFuture (Java 8+)

Асинхронное программирование с цепочками действий.

CompletableFuture.supplyAsync(() -> fetchData())
.thenApply(data -> process(data))
.thenAccept(result -> System.out.println(result));

14. Работа с файлами и вводом-выводом

14.1. Потоки ввода-вывода

  • InputStream / OutputStream — байтовые
  • Reader / Writer — символьные

14.2. Файловые операции (NIO.2, Java 7+)

Пакет java.nio.file:

  • Path — путь к файлу
  • Files — статические методы (readAllLines, write, copy, delete)
  • Paths.get("...") — создание объекта Path

Пример:

List<String> lines = Files.readAllLines(Paths.get("input.txt"));
Files.write(Paths.get("output.txt"), lines);

14.3. Сериализация

Класс должен реализовывать Serializable.

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.ser"));
oos.writeObject(obj);

15. Аннотации (Annotations)

15.1. Встроенные аннотации

  • @Override — переопределение метода
  • @Deprecated — устаревший код
  • @SuppressWarnings — подавление предупреждений

15.2. Создание собственных аннотаций

public @interface Author {
String name();
int version() default 1;
}

Использование:

@Author(name = "Timur", version = 2)
public class MyClass { ... }

15.3. Retention и Target

  • @Retention(RetentionPolicy.RUNTIME) — доступна во время выполнения
  • @Target(ElementType.METHOD) — применима только к методам

16. Модульная система (Project Jigsaw, Java 9+)

16.1. module-info.java

module com.example.myapp {
requires java.base;
requires java.sql;
exports com.example.myapp.api;
}

16.2. Преимущества

  • Явные зависимости
  • Инкапсуляция пакетов
  • Улучшенная производительность запуска

17. Стандартная библиотека: ключевые пакеты

ПакетНазначение
java.langОсновные классы (Object, String, Math, System)
java.utilКоллекции, дата/время, Scanner, Random
java.ioПотоки ввода-вывода
java.nioНовые I/O операции
java.netСетевое взаимодействие
java.timeСовременный API даты и времени (Java 8+)
java.textФорматирование текста, чисел, дат
java.mathBigInteger, BigDecimal
java.securityКриптография, подписи
javax.cryptoШифрование

18. Дата и время (java.time)

18.1. Основные классы

  • LocalDateTime — дата и время без часового пояса
  • ZonedDateTime — с часовым поясом
  • Instant — момент времени в UTC
  • Duration — временной промежуток в секундах/наносекундах
  • Period — период в годах, месяцах, днях

18.2. Пример

LocalDateTime now = LocalDateTime.now();
LocalDateTime future = now.plusDays(7);
long days = ChronoUnit.DAYS.between(now, future);

19. Работа с JSON и XML

19.1. JSON

Java не включает встроенную поддержку JSON в стандартную библиотеку до Java EE / Jakarta EE, но широко используются сторонние библиотеки:

Jackson (наиболее популярная)

ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(person);
Person p = mapper.readValue(json, Person.class);

Gson (от Google)

Gson gson = new Gson();
String json = gson.toJson(person);
Person p = gson.fromJson(json, Person.class);

19.2. XML

DOM-парсинг (в памяти)

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File("data.xml"));

SAX-парсинг (событийный, потоковый)

Подходит для больших файлов, потребляет меньше памяти.

JAXB (Java Architecture for XML Binding, устарел в Java 11, восстановлен в Jakarta EE)

Аннотации позволяют преобразовывать объекты в XML и обратно:

@XmlRootElement
public class Person {
@XmlElement
public String name;
}

20. Сетевое программирование

20.1. Низкоуровневые сокеты

TCP (Socket / ServerSocket)

// Сервер
ServerSocket server = new ServerSocket(8080);
Socket client = server.accept();

// Клиент
Socket socket = new Socket("localhost", 8080);

UDP (DatagramSocket)

DatagramSocket socket = new DatagramSocket();
byte[] buffer = "Hello".getBytes();
InetAddress address = InetAddress.getByName("localhost");
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, address, 9000);
socket.send(packet);

20.2. HTTP-клиент (Java 11+)

Встроенная поддержка HTTP/2:

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/data"))
.build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

Для более сложных сценариев используются библиотеки: Apache HttpClient, OkHttp.


21. JDBC (Java Database Connectivity)

21.1. Подключение к базе

String url = "jdbc:postgresql://localhost:5432/mydb";
String user = "user";
String password = "pass";

Connection conn = DriverManager.getConnection(url, user, password);

21.2. Выполнение запросов

Statement (без параметров)

Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users");

PreparedStatement (с параметрами, защита от SQL-инъекций)

PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE id = ?");
ps.setInt(1, userId);
ResultSet rs = ps.executeQuery();

21.3. Обработка результата

while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
}

21.4. Транзакции

conn.setAutoCommit(false);
try {
// несколько операций
conn.commit();
} catch (SQLException e) {
conn.rollback();
}

21.5. Пулы соединений

Используются в production: HikariCP, Apache DBCP, C3P0.


22. Модульное тестирование

22.1. JUnit 5 (современный стандарт)

Аннотации

  • @Test — метод теста
  • @BeforeEach, @AfterEach — перед/после каждого теста
  • @BeforeAll, @AfterAll — статические методы, один раз на класс
  • @Disabled — пропустить тест

Утверждения (Assertions)

assertEquals(expected, actual);
assertTrue(condition);
assertThrows(IllegalArgumentException.class, () -> method());

22.2. Mockito (моки)

List mockedList = Mockito.mock(List.class);
when(mockedList.get(0)).thenReturn("first");
assertEquals("first", mockedList.get(0));
verify(mockedList).get(0);

23. Сборка проектов

23.1. Maven

Файл pom.xml определяет проект, зависимости, плагины.

<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
</dependencies>

Команды:

  • mvn compile
  • mvn test
  • mvn package
  • mvn clean install

23.2. Gradle

Файл build.gradle (Groovy или Kotlin DSL):

dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
}

Команды:

  • ./gradlew build
  • ./gradlew test
  • ./gradlew run

Gradle использует инкрементальную сборку и кэширование, что ускоряет повторные сборки.


24. JVM: параметры запуска и настройка

24.1. Основные параметры памяти

  • -Xms<size> — начальный размер heap
  • -Xmx<size> — максимальный размер heap
  • -XX:MetaspaceSize — размер метапространства (заменяет PermGen)
  • -Xss<size> — размер стека потока

Пример:

java -Xms512m -Xmx2g -jar app.jar

24.2. Сборка мусора (Garbage Collection)

Выбор GC:

  • -XX:+UseSerialGC — однопоточный (для малых приложений)
  • -XX:+UseParallelGC — многопоточный (высокая пропускная способность)
  • -XX:+UseG1GC — G1 (баланс между задержкой и пропускной способностью)
  • -XX:+UseZGC — Z Garbage Collector (низкие паузы, Java 11+)
  • -XX:+UseShenandoahGC — альтернатива с низкими паузами

24.3. Отладка и профилирование

  • -XX:+PrintGCDetails — вывод информации о GC
  • -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 — удалённая отладка
  • -XX:+HeapDumpOnOutOfMemoryError — дамп памяти при OOM

25. Профилирование и мониторинг

25.1. Встроенные инструменты JDK

  • jps — список Java-процессов
  • jstat — статистика GC и heap
  • jstack — дамп стеков потоков
  • jmap — информация о памяти, heap dump
  • jconsole, jvisualvm — графические инструменты мониторинга
  • jcmd — универсальная команда для отправки команд процессу

25.2. Внешние инструменты

  • VisualVM — расширенный мониторинг
  • YourKit, JProfiler — коммерческие профайлеры
  • Prometheus + Micrometer — метрики в production

26. Отладка

26.1. Логирование

Используйте фреймворки вместо System.out.println:

  • SLF4J — фасад
  • Logback или Log4j2 — реализации

Пример:

private static final Logger log = LoggerFactory.getLogger(MyClass.class);
log.info("Processing user: {}", userId);

26.2. IDE-отладка

  • Точки останова (breakpoints)
  • Пошаговое выполнение (step into / over / out)
  • Инспекция переменных
  • Вычисление выражений во время отладки

27. Лучшие практики разработки на Java

27.1. Именование

  • Классы — UpperCamelCase
  • Методы и переменные — lowerCamelCase
  • Константы — UPPER_SNAKE_CASE
  • Пакеты — строчные, без подчёркиваний (com.example.project)

27.2. Читаемость кода

  • Методы короткие (до 20–30 строк)
  • Одна ответственность на метод
  • Избегать глубокой вложенности условий
  • Использовать выразительные имена

27.3. Безопасность

  • Не логировать чувствительные данные (пароли, токены)
  • Валидировать входные данные
  • Использовать PreparedStatement вместо конкатенации SQL
  • Обновлять зависимости (CVE-уязвимости)

27.4. Производительность

  • Избегать создания лишних объектов в циклах
  • Использовать StringBuilder для конкатенации строк в цикле
  • Предпочитать примитивы обёрткам, где возможно
  • Использовать пул соединений и потоков

27.5. Обработка ошибок

  • Не игнорировать исключения
  • Логировать причину ошибки (e.getMessage(), e.getCause())
  • Не выбрасывать исключения из блоков finally
  • Использовать конкретные типы исключений

27.6. Неизменяемость

  • Делать классы неизменяемыми, когда это возможно (final поля, отсутствие сеттеров)
  • Использовать Collections.unmodifiableList() для защиты коллекций

27.7. Совместимость

  • Указывать версию языка в pom.xml или build.gradle
  • Избегать использования preview-функций в production
  • Тестировать на целевой версии JVM